﻿using Prism.Interactivity;
using System;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using System.Windows.Input;

namespace Base.ModuleBase.Attachs
{
    public class DoubleTouchCommandBehavior: CommandBehaviorBase<UIElement>
    {
        private static TaskCompletionSource<TouchResult> _tcs;
        public DoubleTouchCommandBehavior(UIElement element)
            : base(element)
        {
            element.PreviewTouchDown += Element_TouchDown; // 触屏点击
            element.PreviewMouseLeftButtonDown += Element_MouseLeftButtonDown; // 鼠标点击
        }

        private void Element_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
        {
            if (e.StylusDevice == null)
            {
                //StylusDevice==null是鼠标事件，!=null是触摸转鼠标事件
                OnClick(sender, e.GetPosition(null));
            }
        }

        /// <summary>
        /// 触摸点击
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Element_TouchDown(object sender, TouchEventArgs e)
        {
            OnClick(sender, e.GetTouchPoint(null).Position);
        }

        private void OnClick(object sender, Point touchPoint)
        {
            // 第二次点击到来，给任务赋值
            if (_tcs != null && !_tcs.Task.IsCompleted && !_tcs.Task.IsCanceled)
            {
                _tcs.TrySetResult(new TouchResult { CommandParameter = CommandParameter, Source = sender, Point = touchPoint });
            }
            // 第一次点击到来，则等待第二次点击
            else
            {
                _ = WaitAndClickOther(sender, touchPoint);
            }
        }

        /// <summary>
        /// 等待第二次按下
        /// </summary>
        /// <param name="first">第一次按键</param>
        /// <returns></returns>
        private async Task WaitAndClickOther(object sender, Point touchPoint)
        {
            _tcs = new TaskCompletionSource<TouchResult>();

            // 登记第二次点击任务结果，则双击任务取消结束
            var second = await _tcs.WithCancellation(new CancellationTokenSource(TouchInerval).Token);

            var dy = touchPoint.Y - second.Point.Y;
            var dx = touchPoint.X - second.Point.X;
            // 验证同一控件，坐标范围
            if (sender != second.Source || Math.Abs(dx) > TouchRange || Math.Abs(dy) > TouchRange)
                return;

            ExecuteCommand(second.CommandParameter);
        }

        public int TouchInerval { get; set; } = DoubleTouchAttach.TouchInervalDefaultValue;

        public int TouchRange { get; set; } = DoubleTouchAttach.TouchRangeDefaultValue;
    }
}
